#include "stm32f10x.h"
#include "stdio.h"

/** 
 * 0-sigle byte 1-hex packet 2-utf8 4-robot
 */
uint8_t receive_mode = 0;
uint8_t receive;
uint8_t receive_flag = 0;
/** 
 * 0-准备接收 1-接收中 2-等待结束
 */
uint8_t receive_flag_hex_packet = 0;
/**
 * 0-准备接收 1-接收中 2-等待结束 
 */
uint8_t receive_flag_utf8_packet = 0;

uint8_t receive_hex_packet[4];
uint8_t receive_hex_packet_idx = 0;

uint8_t receive_utf8_packet_idx = 0;
uint8_t receive_utf8_packet[20];
void Usart_Init_TR(void)
{
    // enable apb2 clock 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    // enable gpioa clock
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    

    // init gpioa9 
    GPIO_InitTypeDef GPIO_InitParam;
    GPIO_InitParam.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitParam.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitParam.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitParam);
    // init  gpioa10 
    GPIO_InitParam.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitParam.GPIO_Pin = GPIO_Pin_10;
    GPIO_Init(GPIOA, &GPIO_InitParam);

    // init usart1 
    USART_InitTypeDef USART_InitParam;
    USART_InitParam.USART_BaudRate = 9600;
    USART_InitParam.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitParam.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_InitParam.USART_Parity = USART_Parity_No;
    USART_InitParam.USART_StopBits = USART_StopBits_1;
    USART_InitParam.USART_WordLength = USART_WordLength_8b;
    USART_Init(USART1, &USART_InitParam);

    // config it 
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    // config it group
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    // config nvme
    NVIC_InitTypeDef NVIC_InitParam;
    NVIC_InitParam.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitParam.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitParam.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitParam.NVIC_IRQChannelSubPriority = 0;
    NVIC_Init(&NVIC_InitParam);
    
    // enable usart1
    USART_Cmd(USART1, ENABLE);

}
// config usart1 it
void Usart_Init(void)
{
    // enable apb2 clock
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    // init gpio pa9 usart-tx
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitTypeDef GPIO_InitParam;
    GPIO_InitParam.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitParam.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitParam.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitParam);

    // init usart1
    USART_InitTypeDef USART_InitParam;
    USART_InitParam.USART_BaudRate = 9600;
    USART_InitParam.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitParam.USART_Mode = USART_Mode_Tx;
    USART_InitParam.USART_Parity = USART_Parity_No;
    USART_InitParam.USART_StopBits = USART_StopBits_1;
    USART_InitParam.USART_WordLength = USART_WordLength_8b;
    USART_Init(USART1, &USART_InitParam);

    // enable usart1
    USART_Cmd(USART1, ENABLE);

}

void Usart_SendByte(uint16_t Hex) 
{
    USART_SendData(USART1, Hex);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE)== RESET);

}
void Usart_SendArray(uint16_t *Array, uint16_t Length)
{
    for (int i = 0; i < Length; i++)
    {
        Usart_SendByte(Array[i]);
    }

}
void Usart_SendString(char *Array) 
{
	for (int i = 0; Array[i] != '\0'; i++)
    {
        Usart_SendByte(Array[i]);
    }

}
/** 
 * 将printf函数重定向到串口输出
 */
int fputc(int Num, FILE *f)
{
    Usart_SendByte(Num);
    return Num;
}


uint8_t GetReceiveFlag(void)
{
    uint8_t tmp = receive_flag;
    receive_flag = 0;
    return tmp;
}

uint8_t GetReceive(void)
{
    return receive;
}

void Usart_SendHexPacket(uint8_t *Array, uint8_t Length)
{
   Usart_SendByte(0xFF);
   Usart_SendArray(Array, Length);
   Usart_SendByte(0xFE);
}

void Usart_Send_SingleRobotCommand(uint8_t Idx, uint16_t Pos)
{
    char Char[4];
   Usart_SendByte('#');
   Usart_SendByte('0' + Idx);
   Usart_SendByte('P');
   sprintf(Char,"%04d", Pos);
   for (int i = 0; i < 4; i++)
   {
    Usart_SendByte(Char[i]);
   }

//    Usart_SendByte('0');
//    Usart_SendByte('5');
//    Usart_SendByte('0');
//    Usart_SendByte('0');

}
void Usart_SendRobotCommand( uint16_t Pos1, uint16_t Pos2, uint16_t Pos3, uint16_t Pos4, uint16_t Pos5, uint16_t Pos6)
{
    // #1P1500T1000
    Usart_Send_SingleRobotCommand(1, Pos1);
    Usart_Send_SingleRobotCommand(2, Pos2);
    Usart_Send_SingleRobotCommand(3, Pos3);
    Usart_Send_SingleRobotCommand(4, Pos4);
    Usart_Send_SingleRobotCommand(5, Pos5);
    Usart_Send_SingleRobotCommand(6, Pos6);
    Usart_SendByte('T');
    Usart_SendByte('1');
    Usart_SendByte('0');
    Usart_SendByte('0');
    Usart_SendByte('0');
    Usart_SendByte('\r');
    Usart_SendByte('\n');
}
void Usart_ReceiveUtf8Packet(void)
{
    receive = USART_ReceiveData(USART1);
    if (receive_flag_utf8_packet == 0 && receive == '@')
    {
        receive_flag_utf8_packet = 1;
        receive_flag = 0;
        for (int i = 0; i < 20; i++)
        {
            receive_utf8_packet[i]= ' ';
        }
    } else if (receive_flag_utf8_packet == 1)
    {
        if (receive == '&')
        {
            receive_utf8_packet_idx = 0;
            receive_flag_utf8_packet = 0;
            receive_flag = 1;
            return;
        }

        receive_utf8_packet[receive_utf8_packet_idx++] = receive;
    }
}
void Usart_ReceiveRobotCmd()
{
    receive = USART_ReceiveData(USART1);
    if (receive_flag_utf8_packet == 0 && receive == '#')
    {
        receive_flag_utf8_packet = 1;
        receive_flag = 0;
        for (int i = 0; i < 20; i++)
        {
            receive_utf8_packet[i]= ' ';
        }
    } else if (receive_flag_utf8_packet == 1)
    {
        if (receive == '\r')
        {
            receive_flag_utf8_packet = 2;
        } else{
            receive_utf8_packet[receive_utf8_packet_idx++] = receive;
        }

    } else if (receive_flag_utf8_packet == 2 && receive == '\n')
    {
            receive_utf8_packet_idx = 0;
            receive_flag_utf8_packet = 0;
            receive_flag = 1;
    }
}

void Usart_ReceiveHexPacket(void)
{
    receive = USART_ReceiveData(USART1);
    if (receive_flag_hex_packet == 0 && receive == 0xFF)
    {
        receive_flag_hex_packet = 1;
        receive_flag = 0;
    } else if (receive_flag_hex_packet == 1)
    {
        receive_hex_packet[receive_hex_packet_idx++] = receive;
        if(receive_hex_packet_idx > 3)
        {
            receive_hex_packet_idx = 0;
            // waiting end flag
            receive_flag_hex_packet = 2;
        }
    } else if (receive_flag_hex_packet == 2 && receive == 0xFE)
    {
        receive_flag_hex_packet = 0;
        receive_flag = 1;
    }

}


void Usart_SetReceiveMode(uint8_t Mode)
{
    receive_mode = Mode;
}
uint8_t Usart_GetReceiveMode()
{
    return receive_mode;
}

uint8_t* Usart_GetReceivePacket()
{
    return  receive_mode == 1 ? receive_hex_packet : receive_utf8_packet;
}


void USART1_IRQHandler(void)
{
    if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET) 
    {
        if (receive_mode == 0)
        {
            receive = USART_ReceiveData(USART1);
            receive_flag = 1;
        }
        if (receive_mode == 1)
        {
            Usart_ReceiveHexPacket();
        }
        
        if (receive_mode == 2)
        {
            Usart_ReceiveUtf8Packet();
        }
        if (receive_mode == 4)
        {
            Usart_ReceiveRobotCmd();
        }

    }

}